package com.lightboat.common.algorithm;

import java.util.List;

/**
 * 根据抽取数据数量和权重总和动态选择算法的智能抽取系统
 */
public class SmartLotteryService<T> {

    private static final int SPACE_TIME_THRESHOLD = 100_0000;  // 100万阈值
    private static final int PRIZE_COUNT_THRESHOLD = 1000;      // 抽取数据数量阈值

    /**
     * 智能选择抽取算法
     */
    public WeightedLotteryWheel.Prize<T> smartDraw(List<WeightedLotteryWheel.Prize<T>> prizes) {
        // 计算总权重
        long totalWeight = prizes.stream().mapToLong(WeightedLotteryWheel.Prize<T>::getWeight).sum();

        // 根据阈值选择算法
        if (shouldUseSpaceForTime(prizes.size(), totalWeight)) {
            return drawWithSpaceForTime(prizes);
        } else {
            return drawWithTimeForSpace(prizes);
        }
    }

    /**
     * 判断是否应该使用空间换时间策略
     */
    private boolean shouldUseSpaceForTime(int prizeCount, long totalWeight) {
        // 策略1：权重总和超过阈值时使用时间换空间
        if (totalWeight > SPACE_TIME_THRESHOLD) {
            return false;
        }

        // 策略2：抽取数据数量很少时直接使用时间换空间
        if (prizeCount < 10) {
            return false;
        }

        // 策略3：综合考虑抽取数据数量和权重
        return prizeCount <= PRIZE_COUNT_THRESHOLD || totalWeight <= 10000;
    }

    private WeightedLotteryWheel.Prize<T> drawWithSpaceForTime(List<WeightedLotteryWheel.Prize<T>> prizes) {
        // 使用空间换时间算法
        WeightedLotteryWheel<T> lottery = new WeightedLotteryWheel<>(prizes);
        return lottery.drawPrize();
    }

    private WeightedLotteryWheel.Prize<T> drawWithTimeForSpace(List<WeightedLotteryWheel.Prize<T>> prizes) {
        // 使用时间换空间算法
        RealTimeLottery<T> lottery = new RealTimeLottery<>(prizes);
        return lottery.drawPrize();
    }
}